package com.shuqi.download.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import com.shuqi.application.ShuqiApplication;
import com.shuqi.common.Config;

/**
 * 下载功能工具类
 * @author GaoPeng<gaopeng@ucweb.com>
 *
 */
public class Util {

	/**
     * 获取Http响应头字段
     * @param http
     * @return
     */
    public static Map<String, String> getHttpResponseHeader(HttpURLConnection http) {
        Map<String, String> header = new LinkedHashMap<String, String>();
        
        for (int i = 0;; i++) {
            String mine = http.getHeaderField(i);
            if (mine == null) break;
            header.put(http.getHeaderFieldKey(i), mine);
        }
        
        return header;
    }
    
	/**
     * 打印Http头字段
     * @param http
     */
    public static void printResponseHeader(HttpURLConnection http){
        Map<String, String> header = getHttpResponseHeader(http);
        
        for(Map.Entry<String, String> entry : header.entrySet()){
            String key = entry.getKey()!=null ? entry.getKey()+ ":" : "";
            System.out.println(key+ entry.getValue());
        }
    }
    
    /**
     * 获取文件名
     * @param conn
     * @return
     */
    public static String getFileName(String url,HttpURLConnection conn) {
        String filename = url.substring(url.lastIndexOf('/') + 1);
        if(filename==null || "".equals(filename.trim())){//如果获取不到文件名称
            for (int i = 0;; i++) {
                String mine = conn.getHeaderField(i);
                if (mine == null) break;
                if("content-disposition".equals(conn.getHeaderFieldKey(i).toLowerCase())){
                    Matcher m = Pattern.compile(".*filename=(.*)").matcher(mine.toLowerCase());
                    if(m.find()) return m.group(1);
                }
            }
            filename = UUID.randomUUID()+ ".tmp";//默认取一个文件名
        }
        return filename;
    }
    
    /**
     * 根据大小及分区数获取区间值
     * @param s
     * @param n
     * @return
     */
    public static int[][] getRegion(int s,int n) {
    	int[][] a=new int[n][2];
    	int i=s%n;
    	System.out.println(i);
    	int j=s/n;
    	int k=0;
    	int l=-1;
		for(;k<n;k++) {
			a[k][0]=l+1;
			l+=j;
			a[k][1]=(k==(n-1)&&i>0)?l+i:l;
		}
    	return a;
    }
    
    /**
	 * 判断下载文件是否损坏
	 * @param fileSize
	 * @return
	 */
	public static boolean isFileDamage(String filePath,int fileSize) {
		try {
			File file=new File(filePath);
			if(file!=null&&file.exists()&&file.length()==fileSize) {
				return false;
			}
		} catch(Exception e) {
			System.out.println("文件读取失败");
			e.printStackTrace();
		}
		return true;
	}
	
	/**
	 * 获取网络类型（包装）
	 * @return
	 */
	public static String getNetType() {
	    return Config.getNetType(ShuqiApplication.getContext());
	}
	
	/**
	 * 判断是否为WAP网络
	 * @return
	 */
	public static boolean isWapNet() {
	    // 获取网络类型
        String netType=Util.getNetType();
        Util.log("网络类型："+netType);
        if(netType!=null&&(netType.equalsIgnoreCase("uniwap")||netType.equalsIgnoreCase("cmwap")||netType.equalsIgnoreCase("3gwap"))) {
            return true;
        } else {
            return false;
        }
	}
	
	/**
     * 判断是否为高速网络（目前还未考虑4G及非联通3G）
     * @return
     */
    public static boolean isHighNet() {
        // 获取网络类型
        String netType=Util.getNetType();
        if(netType!=null&&(netType.equalsIgnoreCase("wifi")||netType.equalsIgnoreCase("3gnet"))) {
            return true;
        } else {
            return false;
        }
    }
	
	/**
     * 获取网络连接
     * @param fileUrl
     * @param range
     * @return
     */
    public static HttpURLConnection getConnection(String fileUrl,String range) {
		HttpURLConnection conn=null;
		URL url;
		try {
			url = new URL(fileUrl);
			if(isWapNet()) {
//			    Proxy proxy = new Proxy(java.net.Proxy.Type.HTTP,new InetSocketAddress("10.0.0.172", 80));
//			    conn=(HttpURLConnection)url.openConnection(proxy);
//			    //conn.setRequestProperty("X-Online-Host", url.getHost());
//			    //conn.setDoInput(true);
	            String host = url.getHost();
	            String path = "http://10.0.0.172:80" + url.getFile();
	            URL url2 = new URL(path);
	            conn = (HttpURLConnection) url2.openConnection();
	            conn.setRequestProperty("X-Online-Host", host);
//	            conn.setDoInput(true);
			} else {
			    conn=(HttpURLConnection)url.openConnection();
			}
			if(conn!=null) {
			    conn.setConnectTimeout(15000);
	            conn.setReadTimeout(15000);
	            conn.setRequestMethod("GET");
	            //conn.setRequestProperty("Accept", "image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*");
	            conn.setRequestProperty("Accept-Language", "zh-CN");
	            //conn.setRequestProperty("Referer", fileUrl); 
	            conn.setRequestProperty("Charset", "UTF-8");
	            conn.setRequestProperty("User-Agent", "Mozilla/5.0(Linux;U;Android 2.2.1;en-us;Nexus One Build.FRG83) AppleWebKit/553.1(KHTML,like Gecko) Version/4.0 Mobile Safari/533.1");
	            //conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)");
	            if(!isEmpty(range)) conn.setRequestProperty("RANGE", "bytes=" + range);
	            conn.setRequestProperty("Connection", "Keep-Alive");
	            //conn.setRequestProperty("IP-SRC", "shuqi_" + netType);
	            //conn.setRequestProperty("aak", ConfigVersion.getAppApiKey());
	            //conn.setRequestProperty("Accept-Encoding", "gzip");
	            conn.setRequestProperty("Accept-Encoding", "");// 屏蔽下载的gzip压缩操作
	            conn.connect();
	            //Util.printResponseHeader(conn);
			}
		} catch (Exception e) {
			e.printStackTrace();
			if(conn!=null) {
			    conn.disconnect();
			    conn=null;
			}
		}
		return conn;
	}
	
	/**
     * 获取网络连接
     * @param fileUrl   请求地址
     * @param range     断点续传时的RANGE范围
     * @param length    最小返回数据大小
     * @param retry     失败后重试次数
     * @return
     */
    public static HttpURLConnection getConnection(String fileUrl,String range,int length,int retry) {
        HttpURLConnection conn=getConnection(fileUrl,range);
        try {
            int i=0;
            while((conn==null
                    ||(isEmpty(range)&&conn.getResponseCode()!=200)
                    ||(!isEmpty(range)&&conn.getResponseCode()!=206)
                    ||conn.getContentLength()<length
                    )&&i<retry) {
                i++;
                Util.log("第"+i+"次重新连接网络");
                if(conn!=null) {
                    Util.log("网络连接失败（状态代码："+conn.getResponseCode()+"，数据长度："+conn.getContentLength()+"）");
                    conn.disconnect();
                } else {
                    Util.log("网络连接失败（连接为空）");
                }
                conn=getConnection(fileUrl,range);
            }
        } catch(Exception e) {
            e.printStackTrace();
        }
        return conn;
    }
    
	/**
	 * 判断字符串是否为空
	 * 
	 * @param str
	 * @return
	 */
	public static boolean isEmpty(String str) {
		if (str == null || str.trim().equalsIgnoreCase("")) {
			return true;
		} else {
			return false;
		}
	}
	
	/**
	 * 通过文件路径获取所在目录
	 * @param filepath
	 * @return
	 */
	public static String getFileFolder(String filepath) {
		int i=filepath.lastIndexOf("/");
		int j=filepath.lastIndexOf("\\");
		if(i>0||j>0) {
			return filepath.substring(0,(i>j?i:j)+1);
		}
		return null;
	}
	
	/**
     * 解压文件（不支持UTF-8）
     * @param src   源包路径
     * @param dest  解压路径
     * @param del   是否删除源包（默认为否）
     * @return
     */
    public static boolean unzip(String src,String dest,boolean del) {
        try {
            // 解压目录不存在时创建目录
            File destFolder = new File(dest);
            if(!destFolder.exists()) {
                destFolder.mkdirs();
            }
            ZipInputStream input = new ZipInputStream(new BufferedInputStream(new FileInputStream(src)));
            ZipEntry entry = null;
            // 归档计数
            int i=0;
            while((entry = input.getNextEntry()) != null) {
                i++;
                File tmpFile = new File(dest + "/" + entry.getName());
                tmpFile.getParentFile().mkdirs();
                if(entry.isDirectory()) {
                    tmpFile.mkdir();
                } else {
                    BufferedOutputStream output = new BufferedOutputStream(new FileOutputStream(tmpFile));
                    byte[] datas = new byte[1024];
                    int count;
                    while((count = input.read(datas)) != -1) {
                        output.write(datas, 0, count);
                    }
                    output.close();
                }
                input.closeEntry();
            }
            input.close();
            if(i==0) {
                throw new Exception("解压文件失败（压缩文件损坏）");
            }
            if(del) {
                File file=new File(src);
                if (file.isFile() && file.exists()) { 
                    file.delete();
                } else {
                    throw new Exception("缓存文件删除失败");
                }
            }
            return true;
        } catch(Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    
    /**
     * 解压文件（不支持UTF-8）
     * @param src   源包路径
     * @param dest  解压路径
     * @param del   是否删除源包（默认为否）
     * @param retry 失败后重试次数
     * @return
     */
    public static boolean unzip(String src,String dest,boolean del,int retry) {
        boolean tag=unzip(src,dest,del);
        int i=0;
        while(!tag&&i<retry) {
            i++;
            Util.log("第"+i+"次重新解压文件");
            tag=unzip(src,dest,del);
        }
        return tag;
    }
	
	/**
	 * 返回解析后的下载文件名
	 * @param uid
	 * @param bid
	 */
	public static String parseFileName(String uid,String bid) {
		return uid+"_"+bid+".sqb";
	}
	
	/**
     * 打印日志
     * @param message
     */
    public static void log(String message) {
        System.out.println("[download]"+message);
    }
    
    /**
     * 获取百分比
     * @param downLength
     * @param totalLength
     * @return
     */
    public static float getPercent(int downLength,int totalLength) {
        float percent=(float)(Math.round(((float)downLength*100/totalLength)*100))/100;
        if(percent>100) percent=100;
        return percent;
    }
}
